package com.mangofactory.aop.configuration
{
	import com.mangofactory.aop.aspects.Aspect;
	
	import flash.utils.getQualifiedClassName;
	
	import org.as3commons.reflect.Method;
	import org.as3commons.reflect.Type;

	public class PatternMatchingProxyPolicy implements ProxyPolicy
	{
		public static const ANY_METHOD:String = "."; // Regex for Any Char
		private var classPattern:String
		private var methodPattern:String;
		private var aspects:Vector.<Aspect>
		private var excludedMethodNames:Array = ["hasOwnProperty","propertyIsEnumerable","isPrototypeOf"]
		public function PatternMatchingProxyPolicy(classPattern:String,methodPattern:String,aspects:Vector.<Aspect>)
		{
			this.classPattern = classPattern;
			this.methodPattern = methodPattern;
			this.aspects = aspects;
		}
		
		/**
		 * Creates a new builder for constructing a PattternMatchingProxyPolicy.
		 * The classPattern should be a string which will match against desired classes.
		 * Wildcards are supported
		 * */
		public static function forClasses(classPattern:String):PatternMatchingProxyPolicyBuilder
		{
			return new PatternMatchingProxyPolicyBuilder(classPattern);
		}

		public function requiresProxy(clazz:Class):Boolean
		{
			var className:String = getQualifiedClassName(clazz);
			className = className.replace("::",".");
			return className.match(classPattern) != null;
		}

		public function getAspectsForMethod(method:Method):Vector.<Aspect>
		{
			return aspects;
		}

		public function getMethodsToProxy(type:Type):Vector.<Method>
		{
			var methods:Vector.<Method> = new Vector.<Method>();
			for each (var method:Method in type.methods)
			{
				if (excludedMethodNames.indexOf(method.name) != -1)
					continue;
				
				if (method.name.match(methodPattern))
					methods.push(method);
			}
			return methods;
		}
	}
}